# Interpreted Tests for JVMTI code.
# These tests are used to test JVMTI functions in a purley interpreted setting
# This file compiles the JNI code into a shared object, then invokes gij to run
# the test.


# Compile a single C file and produce a .so file.  OPTIONS is a list
# of options to pass to the compiler.  Returns 0 on failure, 1 on
# success.
proc gcj_jni_compile_c_to_so {file {options {}}} {
  global srcdir subdir
  global host_triplet
  verbose "options: $options"
  set options_cxx $options
  set options ""

# Apple uses a different extension for shared/dynamic libraries
# so we check against powerpc-apple-darwin and set them to
# dylib.
# HP-UX uses sl, so we check this too, otherwise we take so.

  if { [istarget "*-*-darwin*"] } {
      set so_extension "dylib"
      set so_flag "-dynamiclib"
  } elseif { [istarget "hppa*-hp-hpux*"] } {
      set so_extension "sl"
      set so_flag "-shared"
  } elseif { [istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"] } {
      set so_extension "dll"
      set so_flag "-shared"
  } else {
      set so_extension "so"
      set so_flag "-shared"
  }

  # ARM C++ emits an ABI warning for varargs.
  if { [istarget "arm*"] } {
      lappend options "additional_flags=-Wno-abi"
  }

  set filename [file tail $file]
  set name [file rootname $filename]
  set soname lib${name}.${so_extension}

  lappend options "additional_flags=${so_flag} -fPIC"
  # Find the generated header.
  lappend options "additional_flags=-I. -I.. -I$srcdir/$subdir"

  # Ensure that the generated header has correct prototypes.
  set cfile [file rootname $file].c
  if { [file exists $cfile] } {
      # This option is only valid for C sources.
      lappend options "additional_flags=-Wmissing-prototypes"
  }

  # Find jni.h and jni_md.h.
  lappend options "additional_flags=-I$srcdir/../include  \
                   -I$srcdir/../classpath/include -fdollars-in-identifiers"

  # Append C++ options
  lappend options "additional_flags=$options_cxx"

  set x [libjava_prune_warnings \
	     [target_compile $file $soname executable $options]]
  if {$x != ""} {
      verbose "target_compile failed: $x" 2
      fail "$filename compilation"
      return 0
  }

  pass "$filename compilation"
  return 1
}

# Do all the work for a single JVMTI test.  Return 0 on failure.
proc gij_jvmti_test_one {file} {
  global runtests

  # The base name.  We use it for several purposes.
  set main [file rootname [file tail $file]]
  if {! [runtest_file_p $runtests $main] } {
      # Simply skip it.
      return 1
  }

#  if {! [bytecompile_file $file [pwd]] } {
#     fail "bytecompile $file"
#     # FIXME - should use `untested' on all remaining tests.
#     # But that is hard.
#     return 0
#   }
#   pass "bytecompile $file"

#   if {! [gcj_jvmti_build_headers $file] } {
#     # FIXME
#     return 0
#   }
  
  set cfile [file join [file dirname $file] nat$main.c]
  set cxxflags ""
  set cxxldlibflags {}
  # If there is no `.c' file, assume there is a `.cc' file.
  if {! [file exists $cfile] } {
      set cfile [file join [file dirname $file] nat$main.cc]

      set cxxflaglist {}
      foreach arg [split [libjava_find_lib libstdc++-v3/src stdc++] " "] {
          switch -glob -- $arg {
	          "-L*" {
	              set arg [string range $arg 2 end]
	              lappend cxxldlibflags $arg
	              # Strip the `.libs' directory; we link with libtool which
	              # doesn't need it.
	              set arg "-L[file dirname $arg]"
       	            }
          }
      
          lappend cxxflaglist $arg
          # In case the libstdc++ is not installed yet, we pass the build
          # directory of it to the cxxflaglist.
          lappend cxxflaglist "-L$cxxldlibflags"
      }
      # If you're building the compiler with --prefix set to a place
      # where it's not yet installed, then the linker won't be able to
      # find the libgcc used by libgcj.dylib/libstdc++.dylib. We could pass
      # the -dylib_file option, but that's complicated, and it's much easier
      # to just make the linker find libgcc using -L options.
      if { [istarget "*-*-darwin*"] } {
	  lappend cxxflaglist "-shared-libgcc -lstdc++"
      } else {
	  lappend cxxflaglist "-lstdc++"
      }
      set cxxflags [join $cxxflaglist]
  }

  if {! [gcj_jni_compile_c_to_so $cfile $cxxflags] } {
      # FIXME
      return 0
  }

  libjava_arguments

  set jarfile [file join [file dirname $file] $main.jar]
  set gij_flags {-agentlib:dummyagent}
  if {! [exec_gij $jarfile [file rootname $file].out $cxxldlibflags $gij_flags] } {
      return 0
  }

  # When we succeed we remove all our clutter.
  eval gcj_cleanup [glob -nocomplain -- ${main}.*]  \
                   [list $main.class libnat$main.so]

  return 1
}

# Run the JVMTI tests.
proc gij_jvmti_run {} {
  global srcdir subdir
  global build_triplet host_triplet

  # For now we only test JVMTI on native builds.
  if {$build_triplet == $host_triplet} {

    # Build our dummy JVMTI agent library
    if {![gcj_jni_compile_c_to_so [file join $srcdir $subdir dummyagent.c]]} {
      fail "compiling dummy JVMTI agent"
    } else {
      pass "compiling dummy JVMTI agent"

      catch {lsort [glob -nocomplain ${srcdir}/${subdir}/interp/*.jar]} \
	srcfiles

      foreach x $srcfiles {
	gij_jvmti_test_one $x
      }

      gcj_cleanup libdummyagent.so
    }
  } else {
    verbose "JVMTI tests not run in cross-compilation environment"
  }
}

gij_jvmti_run
